home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / GX Libraries / TextLibrary.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-31  |  12.6 KB  |  440 lines  |  [TEXT/MPS ]

  1.  
  2. /*
  3.     File:        TextLibrary.c
  4.  
  5.     Contains:    graphics libraries - text library
  6.     
  7.     Written by:    Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good, Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink, Chris Yerga
  8.     
  9.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.          <2>      1/9/95    JD        changed 'boolean' to 'Boolean'
  14.          <1>      1/9/95    JD        First checked in.
  15. */
  16.  
  17. #include <Memory.h>
  18. #include <Quickdraw.h>
  19. #include <GXFonts.h>
  20. #include <GXLayout.h>
  21. #include "GraphicsLibraries.h"
  22.  
  23.  
  24. gxShape NewChar(const char data, const gxPoint *position)
  25. {
  26.     return GXNewText(1, (const unsigned char *)&data, position);
  27. }
  28.  
  29.  
  30. void SetChar(gxShape target, const char data, const gxPoint *position)
  31. {
  32.     GXSetText(target, 1, (const unsigned char *)&data, position);
  33. }
  34.  
  35.  
  36. void gDrawChar(const char data, const gxPoint *position)
  37. {
  38.     GXDrawText(1, (const unsigned char *)&data, position);
  39. }
  40.  
  41.  
  42. gxShape NewCString(const char *cString, const gxPoint *position)
  43. {
  44.     register long len = 0;
  45.     register const char *find0 = cString;
  46.  
  47.     while (*find0++ != 0)
  48.         ++len;
  49.     return GXNewText(len, (unsigned char *)cString, position);
  50. }
  51.  
  52.  
  53. void SetCString(gxShape source, const char *cString, const gxPoint *position)
  54. {
  55.     register long len = 0;
  56.     register const char *find0 = cString;
  57.  
  58.     while (*find0++ != 0)
  59.         ++len;
  60.     GXSetText(source, len, (unsigned char *)cString, position);
  61. }
  62.  
  63.  
  64. Fixed FixTextWidth(register const unsigned char *ch, register short len)
  65. {
  66.     gxPoint pt;
  67.     gxShape textShape = GXNewText(len, ch, nil);
  68.     Fixed width = GetShapeAdvance(textShape, &pt)->x;
  69.  
  70.     GXDisposeShape(textShape);
  71.     return width;
  72. }
  73.  
  74.  
  75. Fixed FixCStringWidth(register const char *ch)
  76. {
  77.     register long len = 0;
  78.     register const char *find0 = ch;
  79.  
  80.     while (*find0++ != 0)
  81.         ++len;
  82.     return FixTextWidth((unsigned char *) ch, len);
  83. }
  84.  
  85.  
  86. gxShape NewPString(register const char *pString, register const gxPoint *position)
  87. {
  88.     return GXNewText(*pString, (unsigned char *)pString + 1, position);
  89. }
  90.  
  91.  
  92. void SetPString(register gxShape source, register const char *pString, register const gxPoint *position)
  93. {
  94.     GXSetText(source, *pString, (unsigned char *) pString + 1, position);
  95. }
  96.  
  97.  
  98. Fixed FixPStringWidth(register const char *ch)
  99. {
  100.     return FixTextWidth((unsigned char *) ch + 1, *ch);
  101. }
  102.  
  103.  
  104. Fixed FixCharWidth(char ch)
  105. {
  106.     return FixTextWidth((unsigned char *) &ch, 1);
  107. }
  108.  
  109.  
  110. void DrawCString(register const char *ch, register const gxPoint *position)
  111. {
  112.     register long len = 0;
  113.     register const char *find0 = ch;
  114.  
  115.     while (*find0++ != 0)
  116.         ++len;
  117.     GXDrawText(len, (unsigned char *)ch, position);
  118. }
  119.  
  120.  
  121. void DrawPString(register const char *ch, register const gxPoint *position)
  122. {
  123.     GXDrawText(*ch, (unsigned char *)ch + 1, position);
  124. }
  125.  
  126.  
  127. void SetGlyphText(register gxShape source, register unsigned const char *text, long length)
  128. {
  129.     GXSetGlyphs(source, length, text, nil, nil, nil, nil, nil);
  130. }
  131.  
  132.  
  133. void SetGlyphAdvance(register gxShape source, register const long advanceBits[])
  134. {
  135.     GXSetGlyphs(source, 0, nil, nil, advanceBits, nil, nil, nil);
  136. }
  137.  
  138.  
  139. void SetGlyphStyles(register gxShape source, register const short styleRuns[], register const gxStyle glyphStyles[])
  140. {
  141.     GXSetGlyphs(source, 0, nil, nil, nil, nil, styleRuns, glyphStyles);
  142. }
  143.  
  144.  
  145. long GetGlyphText(register gxShape source, register unsigned char *text)
  146. {
  147.     return GXGetGlyphs(source, nil, text, nil, nil, nil, nil, nil, nil);
  148. }
  149.  
  150.  
  151. long GetGlyphAdvance(register gxShape source, register long advanceBits[])
  152. {
  153.     long length;
  154.  
  155.     GXGetGlyphs(source, &length, nil, nil, advanceBits, nil, nil, nil, nil);
  156.     return length;
  157. }
  158.  
  159.  
  160. long GetGlyphStyles(register gxShape source, register short styleRuns[], register gxStyle glyphStyles[])
  161. {
  162.     long runs;
  163.  
  164.     GXGetGlyphs(source, nil, nil, nil, nil, nil, &runs, styleRuns, glyphStyles);
  165.     return runs;
  166. }
  167.  
  168. #define kBoldnessFactor 18
  169.  
  170. static gxTextFace *SetCommonFace(register commonFace face)
  171. {
  172.     register gxTextFace *newFace;
  173.     register long faceLayers = 1;
  174.     register gxFaceLayer *activeLayer;
  175.     gxTransform italicTransform = nil;
  176.     gxStyle nullStyle = nil;
  177.     Boolean doOutline = (face & outline) != 0;
  178.     Boolean doBold = (face & bold) != 0;
  179.     Boolean doShadow = (face & shadow) != 0;
  180.     Boolean doShadowOutline = (face & shadow+outline) != 0;
  181.     Fixed standardBolding = fixed1/kBoldnessFactor;
  182.     Fixed shadowBolding = ff(3)/(kBoldnessFactor*2);
  183.     Fixed shadowTranslate = 2*standardBolding / 3;
  184.     
  185.     if (face == 0)
  186.         return nil;
  187.     
  188.     {
  189.         register long shadowOutlineLayers = doShadowOutline ? 2 : 0;
  190.         register long underlineLayers = (face & underline) ? doShadowOutline + 2 : 0;
  191.  
  192.         faceLayers = shadowOutlineLayers + underlineLayers + (shadowOutlineLayers == 0);
  193.     }
  194.     if (face & italic) {
  195.         italicTransform = GXNewTransform();
  196.         
  197.         GXSkewTransform(italicTransform, -fixed1/4, 0, 0, 0);
  198.     }
  199.     if (face & underline) {
  200.         nullStyle = GXNewStyle();
  201.         GXSetStyleTextSize(nullStyle, fixed1);
  202.         GXSetStyleFont(nullStyle, 0);
  203.     }
  204.     
  205.     newFace = (gxTextFace *) NewPtr(sizeof(gxTextFace) +  (faceLayers - gxAnyNumber) * sizeof(gxFaceLayer));
  206.     newFace->faceLayers = faceLayers;
  207.     ResetMapping(&newFace->advanceMapping);
  208.     if ( ((face & extend) != 0) ^ ((face & condense) != 0) )
  209.         if (face & extend)
  210.             ScaleMapping(&newFace->advanceMapping, ff(100)/85, fixed1, 0, 0);
  211.         else
  212.             ScaleMapping(&newFace->advanceMapping, ff(85)/100, fixed1, 0, 0);
  213.     
  214.     activeLayer = &newFace->faceLayer[0];
  215.     
  216.     if (doShadowOutline) {
  217.         if (face & underline) {
  218.             /*** doesn't discriminate between outline and shadow ***/
  219.             activeLayer->outlineFill = gxNoFill;
  220.             activeLayer->flags = gxUnderlineAdvanceLayer;
  221.             activeLayer->outlineStyle = GXCopyToStyle(nil, nullStyle);
  222.             activeLayer->outlineTransform = italicTransform ? GXCopyToTransform(nil, italicTransform) : GXNewTransform();
  223.             GXMoveTransform(activeLayer->outlineTransform, 0, ff(2)/kBoldnessFactor);
  224.             activeLayer->boldOutset.x = activeLayer->boldOutset.y = 0;
  225.             ++activeLayer;
  226.             
  227.             activeLayer->outlineFill = gxNoFill;
  228.             activeLayer->flags = gxUnderlineAdvanceLayer;
  229.             activeLayer->outlineStyle = GXCopyToStyle(nil, nullStyle);
  230.             GXSetStylePen(activeLayer->outlineStyle, fixed1/8);
  231.             activeLayer->outlineTransform = italicTransform ? GXCopyToTransform(nil, italicTransform) : GXNewTransform();
  232.             GXMoveTransform(activeLayer->outlineTransform, 0, ff(2+doShadow)/kBoldnessFactor);
  233.             activeLayer->boldOutset.x = activeLayer->boldOutset.y = 0;
  234.             ++activeLayer;
  235.  
  236.             activeLayer->outlineFill = gxNoFill;
  237.             activeLayer->flags = gxUnderlineAdvanceLayer + gxWhiteLayer;
  238.             activeLayer->outlineStyle = GXCopyToStyle(nil, nullStyle);
  239.             GXSetStylePen(activeLayer->outlineStyle, fixed1/16);
  240.             activeLayer->outlineTransform = italicTransform ? GXCopyToTransform(nil, italicTransform) : GXNewTransform();
  241.             GXMoveTransform(activeLayer->outlineTransform, 0, ff(2+doShadow)/kBoldnessFactor);
  242.             activeLayer->boldOutset.x = activeLayer->boldOutset.y = 0;
  243.             ++activeLayer;
  244.         }
  245.         
  246.         activeLayer->outlineFill = gxWindingFill;
  247.         activeLayer->flags = 0;
  248.         activeLayer->outlineStyle = nil;
  249.         activeLayer->boldOutset.x = (doShadow ? shadowBolding : standardBolding) + standardBolding*doBold;
  250.         activeLayer->boldOutset.y = doShadow ? shadowBolding : standardBolding;
  251.         if (doShadow) {
  252.             activeLayer->outlineTransform = italicTransform ? GXCopyToTransform(nil, italicTransform) : GXNewTransform();
  253.             GXMoveTransform(activeLayer->outlineTransform, shadowTranslate, shadowTranslate);
  254.         } else
  255.             activeLayer->outlineTransform = italicTransform ? GXCloneTransform(italicTransform) : nil;
  256.         ++activeLayer;
  257.         
  258.         activeLayer->outlineFill = gxWindingFill;
  259.         activeLayer->flags = gxWhiteLayer;
  260.         activeLayer->outlineStyle = nil;
  261.         activeLayer->outlineTransform = italicTransform ? GXCloneTransform(italicTransform) : nil;
  262.         activeLayer->boldOutset.x = doBold*standardBolding;
  263.         activeLayer->boldOutset.y = 0;  
  264.     } else {
  265.         if (face & underline) {
  266.             activeLayer->outlineFill = gxNoFill;
  267.             activeLayer->flags = gxUnderlineAdvanceLayer;
  268.             activeLayer->outlineStyle = GXCopyToStyle(nil, nullStyle);
  269.             activeLayer->outlineTransform = italicTransform ? GXCopyToTransform(nil, italicTransform) : GXNewTransform();
  270.             GXMoveTransform(activeLayer->outlineTransform, 0, ff(doBold+1)/kBoldnessFactor + shadowTranslate);
  271.             activeLayer->boldOutset.x = activeLayer->boldOutset.y = 0;
  272.             ++activeLayer;
  273.             
  274.             activeLayer->outlineFill = gxNoFill;
  275.             activeLayer->flags = gxUnderlineAdvanceLayer;
  276.             activeLayer->outlineStyle = GXCopyToStyle(nil, nullStyle);
  277.             GXSetStylePen(activeLayer->outlineStyle, fixed1/12);    
  278.             activeLayer->outlineTransform = italicTransform ? GXCopyToTransform(nil, italicTransform) : GXNewTransform();
  279.             GXMoveTransform(activeLayer->outlineTransform, 0, ff(doBold+1)/kBoldnessFactor + shadowTranslate);
  280.             activeLayer->boldOutset.x = activeLayer->boldOutset.y = 0;
  281.             ++activeLayer;
  282.         } 
  283.     
  284.         activeLayer->outlineFill = gxWindingFill;
  285.         activeLayer->flags = 0;
  286.         activeLayer->outlineStyle = nil;
  287.         activeLayer->outlineTransform = italicTransform ? GXCloneTransform(italicTransform) : nil;
  288.         activeLayer->boldOutset.x = doBold * standardBolding;
  289.         activeLayer->boldOutset.y = doBold * standardBolding;
  290.     }
  291.     if (activeLayer != &newFace->faceLayer[faceLayers-1])
  292.         DebugStr((unsigned char *)"\pMiscalculated size of gxTextFace structure");
  293.     
  294.     if (italicTransform)
  295.         GXDisposeTransform(italicTransform);
  296.     if (nullStyle)
  297.         GXDisposeStyle(nullStyle);
  298.         
  299.     return newFace;
  300. }
  301.  
  302.  
  303. static void DisposeFaceParts(gxTextFace *newFace)
  304. {
  305.     long activeLayer = newFace->faceLayers - 1;
  306.  
  307.     do {
  308.         if (newFace->faceLayer[activeLayer].outlineStyle)
  309.             GXDisposeStyle(newFace->faceLayer[activeLayer].outlineStyle);
  310.         if (newFace->faceLayer[activeLayer].outlineTransform)
  311.             GXDisposeTransform(newFace->faceLayer[activeLayer].outlineTransform);
  312.     } while (--activeLayer >= 0);
  313.     DisposePtr((Ptr) newFace);
  314. }
  315.  
  316.  
  317. void SetStyleCommonFace(gxStyle source, commonFace face)
  318. {
  319.     gxTextFace *newFace = SetCommonFace(face);
  320.  
  321.     GXSetStyleFace(source, newFace);
  322.     if (newFace)
  323.         DisposeFaceParts(newFace);
  324. }
  325.  
  326.  
  327. void SetShapeCommonFace(gxShape source, commonFace face)
  328. {
  329.     gxTextFace *newFace = SetCommonFace(face);
  330.  
  331.     GXSetShapeFace(source, newFace);
  332.     if (newFace)
  333.         DisposeFaceParts(newFace);
  334. }
  335.  
  336.  
  337. commonFace GetStyleCommonFace(gxStyle source)
  338. {
  339.     long layers = GXGetStyleFace(source, nil);
  340.  
  341.     if (layers == -1)
  342.         return 0;
  343.     {   gxTextFace *realFacePtr = (gxTextFace *) NewPtr(sizeof(gxTextFace) +  (layers - 1) * sizeof(gxFaceLayer));
  344.         commonFace face = 0;
  345.         long activeLayer = 0;
  346.         gxStyle curStyle;
  347.         gxTransform curTransform;
  348.  
  349.         GXGetStyleFace(source, realFacePtr);
  350.         if (realFacePtr->faceLayers == 2) {
  351.             face |= shadow;
  352.             activeLayer++;
  353.         }
  354.         if (realFacePtr->faceLayer[activeLayer].outlineFill == gxClosedFrameFill)
  355.             face |= outline;
  356.         if (realFacePtr->faceLayer[activeLayer].flags & gxUnderlineAdvanceLayer)
  357.             face |= underline;
  358.         curStyle = realFacePtr->faceLayer[activeLayer].outlineStyle;
  359.         if (curStyle)
  360.         if (realFacePtr->faceLayer[activeLayer].boldOutset.x | realFacePtr->faceLayer[activeLayer].boldOutset.y)
  361.             face |= bold;
  362.         curTransform = realFacePtr->faceLayer[activeLayer].outlineTransform;
  363.         if (curTransform)
  364.         {   gxMapping map;
  365.  
  366.             GXGetTransformMapping(curTransform, &map);
  367.             if (map.map[0][0] >= IntToFixed(100) / 85)
  368.                 face |= extend;
  369.             if (map.map[0][0] <= IntToFixed(85) / 100)
  370.                 face |= condense;
  371.             if (map.map[1][0])
  372.                 face |= italic;
  373.         }
  374.         {   gxFaceLayer *layer = realFacePtr->faceLayer;
  375.  
  376.             while (layers--) {
  377.                 DisposeStyleAt(&layer->outlineStyle);
  378.                 DisposeTransformAt(&layer->outlineTransform);
  379.                 layer++;
  380.             }
  381.         }
  382.         return face;
  383.     }
  384. }
  385.  
  386.  
  387. commonFace GetShapeCommonFace(gxShape source)
  388. {
  389.     return GetStyleCommonFace(GXGetShapeStyle(source));
  390. }
  391.  
  392. #define offsetField(type, field)        ((long) &((type *) 0)->field)
  393.  
  394. gxPoint *GetShapeAdvance(gxShape source, gxPoint *advancePt)
  395. {
  396.     gxShapeType type = GXGetShapeType(source);
  397.  
  398.     switch (type) {
  399.         case gxEmptyType:
  400.         case gxFullType:
  401.     #ifdef debugging
  402.             GXPostGraphicsError(graphic_type_does_not_contain_points);
  403.     #endif
  404.         break;
  405.         case gxPointType:
  406.         case gxLineType:
  407.         case gxCurveType:
  408.         case gxRectangleType:
  409.         case gxPolygonType:
  410.         case gxPathType:
  411.         case gxPictureType:
  412.             {   gxRectangle bounds;
  413.  
  414.                 GXGetShapeBounds(source, 0, &bounds);
  415.                 advancePt->x = bounds.right - bounds.left;
  416.                 advancePt->y = bounds.bottom - bounds.top;
  417.             }
  418.         break;
  419.         case gxTextType:
  420.         case gxGlyphType:
  421.         case gxLayoutType:
  422.             {   long characters;
  423.                 gxPoint *positions;
  424.  
  425.                 if (type == gxTextType)
  426.                     GXGetText(source, &characters, nil, nil);
  427.                 else if (type == gxGlyphType)
  428.                     GXGetGlyphs(source, &characters, nil, nil, nil, nil, nil, nil, nil);
  429.                 else characters = GXGetLayoutGlyphs(source, nil, nil, nil, nil, nil, nil, nil);
  430.                 positions = (gxPoint *) NewPtr((characters + 1) * sizeof(gxPoint));
  431.                 GXGetGlyphMetrics(source, positions, nil, nil);
  432.                 advancePt->x = positions[characters].x - positions[0].x;
  433.                 advancePt->y = positions[characters].y - positions[0].y;
  434.                 DisposePtr((Ptr) positions);
  435.             }
  436.         break;
  437.     }
  438.     return advancePt;
  439. }
  440.